home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 November / Macworld (1999-11).dmg / Updaters / WhiteCap 3.0.4 / WhiteCap Source.sit / WhiteCap Source / WhiteCap.cpp < prev    next >
C/C++ Source or Header  |  1999-08-30  |  17KB  |  785 lines

  1. #include "WhiteCap.h"
  2.  
  3. #include "EgOSUtils.h"
  4.  
  5. #if EG_MAC
  6. #include <Menus.h>
  7. #include <Windows.h>
  8. #include <Palettes.h>
  9.  
  10. #if MACAMP
  11. #include "MacAMP_Visual.h"
  12. extern VPInfoBlock gPlugInfo;
  13. #endif
  14.  
  15.  
  16. #if SOUNDJAM
  17. #include "VisFramework.h"
  18. #endif
  19.  
  20.  
  21. #include "CEgFileSpec.h"
  22. #include "Sample.h"
  23. #include "CEgIOFile.h"
  24.  
  25.  
  26. #define __setupPort        GDHandle        saveDev;                                \
  27.                          GrafPtr            savePort;                                \
  28.                         ::GetGWorld( (GWorldPtr*)(&savePort), &saveDev );        \
  29.                         ::SetPort( mOSPort );                
  30.  
  31.  
  32. #define __restorePort     ::SetGWorld( (GWorldPtr)(savePort), saveDev );            
  33. #endif
  34.  
  35. #if EG_WIN
  36. #define __setupPort
  37. #define __restorePort 
  38. #include "RectUtils.h"
  39.  
  40. #include "vis.h"
  41. extern winampVisModule gWCModule;
  42.  
  43. #endif
  44.  
  45.  
  46.  
  47. WhiteCap::WhiteCap( CEgFileSpec& inPluginsFolder, void* inRefCon ) :
  48.     mPrefs( "WhiteCap Preferences", true ),
  49.     mConfigs( cNoDuplicates_CaseInsensitive, cSortLowToHigh) {
  50.     CEgFileSpec spec;
  51.     UtilStr name, str;
  52.     
  53.     
  54.     mPrefs.Load();
  55.     if ( mPrefs.GetPref( 'Vers' ) != 304 ) {
  56.         mTransitionLo        = 4;
  57.         mTransitionHi        = 15;
  58.         mSlideShowInterval    = 20000;        // Factory: 20 secs per config
  59.         mScrnSaverDelay        = 15 * 60000;    // Factory: 15 mins before screen saver kicks in
  60.         }
  61.     else {
  62.         mTransitionLo        = mPrefs.GetPref( 'TrLo' );
  63.         mTransitionHi        = mPrefs.GetPref( 'TrHi' );
  64.         mSlideShowInterval    = mPrefs.GetPref( 'Slde' ) * 1000;
  65.         mScrnSaverDelay        = mPrefs.GetPref( 'SSvr' ) * 1000 * 60;
  66.     }
  67.     
  68.     mRefCon                = inRefCon;
  69.     mInSlideShowMode    = true;
  70.     mAtFullScreen        = false;
  71.     mOSPort                = NULL;
  72.     mNumWorlds            = 0;
  73.     mFrameCount            = 0;
  74.     mFrameCountStart    = EgOSUtils::CurTimeMS();
  75.     mCurConfigNum        = -1;
  76.     mNextShapeChange    = 0x7FFFFFFF;
  77.     mFramesPer10Secs    = 400;
  78.     mDoingSetPortWin    = false;
  79.     mMouseWillAwaken    = false;
  80.     
  81.     if ( mSlideShowInterval > 0 ) 
  82.         mNextShapeChange = mFrameCountStart + mSlideShowInterval;
  83.  
  84.     BuildConfigList( inPluginsFolder );
  85. }
  86.  
  87.  
  88.  
  89.  
  90. WhiteCap::~WhiteCap() {
  91.  
  92.  
  93.     SetFullScreen( false );
  94.             
  95.     // Rewrite the prefs to disk...
  96.     mPrefs.SetPref( 'Vers', 304 );
  97.     mPrefs.SetPref( 'Slde', mSlideShowInterval / 1000 );
  98.     mPrefs.SetPref( 'SSvr', mScrnSaverDelay / 60000 );
  99.     mPrefs.SetPref( 'TrHi', mTransitionHi );
  100.     mPrefs.SetPref( 'TrLo', mTransitionLo );
  101.     
  102.     #if MACAMP || WINAMP
  103.     Rect r;
  104.     #if MACAMP
  105.     GetWinRect( r );
  106.     #else
  107.     // Very annoying:  in Win32, the call to GetWindowRect() is returning garbage in ~WhiteCap(), so just 
  108.     // forget about saving the window position for now in windows :_(
  109.     r = mWinRectHolder;
  110.     #endif
  111.     mPrefs.SetPref( 'wTop', r.top );
  112.     mPrefs.SetPref( 'wLft', r.left );
  113.     mPrefs.SetPref( 'wBot', r.bottom );
  114.     mPrefs.SetPref( 'wRgt', r.right );
  115.     #endif
  116.     
  117.     mPrefs.Store();    
  118.     
  119.     
  120.     // Delete all the existing worlds
  121.     for ( int i = 0; i < mNumWorlds; i++ )
  122.         delete mWorld[ i ];
  123.     
  124.         
  125.     #if DATA_DUMP
  126.     CEgIOFile oFile;
  127.     CEgFileSpec spec( "WhiteCap Dump" );
  128.     
  129.     oFile.open( &spec );
  130.     if ( oFile.noErr() ) {
  131.         oFile.Write( &mDumpData );
  132.     }
  133.     #endif
  134. }
  135.  
  136.  
  137.  
  138.  
  139.  
  140. bool WhiteCap::PtInTitle( Point inPt ) {
  141.     int i;
  142.     
  143.     Rect r;
  144.     GetWinRect( r );
  145.     
  146.     inPt.v -= r.top;
  147.     inPt.h -= r.left;
  148.         
  149.     for ( i = 0; i < mNumWorlds; i++ ) {
  150.         if ( ::PtInRect( inPt, &mWorld[ i ] -> mTitleRect ) )
  151.             return true;
  152.     }
  153.         
  154.     return false;
  155. }
  156.  
  157.  
  158.  
  159.  
  160. void WhiteCap::SelectConfig() {
  161.     long i, sel, idxOffset;
  162.     Point pt;
  163.     UtilStr name;
  164.  
  165.     EgOSUtils::GetMouse( pt );
  166.     
  167.     // We want to add the menu item "(Start Slide Show)" when we're not in slide show mode
  168.     if ( mInSlideShowMode )
  169.         idxOffset = 0;
  170.     else
  171.         idxOffset = 1;
  172.         
  173.     // If we're in full screen mode, show the mouse ptr
  174.     if ( mAtFullScreen )
  175.         EgOSUtils::ShowCursor();
  176.         
  177.     #if EG_MAC
  178.     MenuHandle    menu;
  179.  
  180.     __setupPort
  181.     
  182.     // If we found a world, show a popup menu to select from the configs
  183.     menu = ::NewMenu( 123, "\p " );
  184.     if ( ! mInSlideShowMode ) {
  185.         ::AppendMenu( menu, "\p " );
  186.         ::SetMenuItemText( menu, 1, "\p(Start Slide Show)" );
  187.     }
  188.     for ( i = 1; mConfigs.FetchSpecName( i, name ); i++ ) {
  189.         ::AppendMenu( menu, "\p " );
  190.         ::SetMenuItemText( menu, i + idxOffset, name.getPasStr() );
  191.     }
  192.     ::CheckItem( menu, mCurConfigNum + idxOffset, true ); 
  193.     ::InsertMenu( menu, -1 );
  194.     sel = ::PopUpMenuSelect( menu, pt.v - 6, pt.h, mCurConfigNum + idxOffset );
  195.     ::DeleteMenu( 123 );
  196.     ::DisposeMenu( menu );
  197.  
  198.     sel = ( sel & 0xFFFF0000 ) ? (sel & 0xFFFF) : 0;
  199.     #endif
  200.     
  201.     
  202.     #if EG_WIN
  203.     long flags;
  204.     
  205.     HMENU myMenu = ::CreatePopupMenu();
  206.     if ( ! mInSlideShowMode )
  207.         ::AppendMenu( myMenu, MF_ENABLED | MF_STRING, 1, "(Start Slide Show)" );
  208.     for ( i = 1; mConfigs.FetchSpecName( i, name ); i++ ) {
  209.         flags = MF_ENABLED | MF_STRING;
  210.         if ( mCurConfigNum == i )
  211.             flags |= MF_CHECKED;
  212.         ::AppendMenu( myMenu, flags, i + idxOffset, name.getCStr() );
  213.     }
  214.     sel = ::TrackPopupMenuEx( myMenu, TPM_RETURNCMD, pt.h, pt.v, mOSPort, NULL );
  215.     ::DestroyMenu( myMenu );
  216.     if ( mAtFullScreen )
  217.         ::SetCapture( mOSPort );
  218.     #endif
  219.     
  220.     if ( sel > 0 ) {
  221.         if ( mInSlideShowMode ) 
  222.             mInSlideShowMode = false;
  223.         else {
  224.             if ( sel == 1 ) {
  225.                 mInSlideShowMode = true;
  226.                 mConfigPlayList.Randomize();
  227.                 sel = mConfigPlayList.Fetch( 1 );  }
  228.             else
  229.                 sel--;
  230.         }
  231.         
  232.         LoadConfig( sel );
  233.     }
  234.         
  235.     __restorePort
  236. }
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246. void WhiteCap::SetFullScreen( bool inFullScreen ) {
  247.         
  248.     #if SOUNDJAM
  249.     VisHandlerData*    handlerData = (VisHandlerData*) mRefCon;
  250.     if ( handlerData ) {
  251.         if ( mAtFullScreen != inFullScreen ) {
  252.             if ( PlayerSetFullScreen(handlerData->appCookie, handlerData->playerProc, inFullScreen) == noErr)
  253.                 mAtFullScreen = inFullScreen;
  254.         }
  255.     }
  256.     #else
  257.     
  258.     
  259.     bool            ok;    
  260.     int                dispNum;
  261.     Point            size;
  262.  
  263.     if ( inFullScreen && ! mAtFullScreen ) {
  264.         
  265.         if ( PixPort::FullscreenAvail() ) {
  266.  
  267.  
  268.             __setupPort
  269.             
  270.             // Update the positon of our win 
  271.             GetWinRect( mWinRectHolder );
  272.             dispNum = PixPort::GetOwningDisplay( *((Point*) &mWinRectHolder) );
  273.             
  274.             #if MACAMP
  275.             if ( gPlugInfo.ma -> EnterFullScreen )
  276.                 gPlugInfo.ma -> EnterFullScreen( cPluginAuthor, cWhiteCapID );
  277.             ::HideWindow( mOSPort );
  278.             #endif    
  279.  
  280.             #if WINAMP
  281.             ::ShowWindow( gWCModule.hwndParent, SW_HIDE | SW_MINIMIZE );
  282.             #endif
  283.                             
  284.             // Put in pref wheather to try 32 before 16 bit color?
  285.             ok = mPort.InitFullscreen( dispNum, size, mOSPort );
  286.             
  287.             if ( ok ) {
  288.  
  289.                 
  290.                 mDispRect.left = 0;
  291.                 mDispRect.top = 0;
  292.                 mDispRect.right = size.h;
  293.                 mDispRect.bottom = size.v;
  294.                 ResizeWorlds();
  295.                 mAtFullScreen = true;
  296.                 mFullscreenStartTime = EgOSUtils::CurTimeMS();
  297.                 
  298.                 // If we don't expire them, there'll be an ugly gap for the time it took to go fullscreen
  299.                 for ( int i = 0; i < mNumWorlds; i++ )
  300.                     mWorld[ i ] -> ExpireSamples(); 
  301.                 }    
  302.             else {
  303.                 #if MACAMP
  304.                 if ( gPlugInfo.ma -> ExitFullScreen )
  305.                     gPlugInfo.ma -> ExitFullScreen();
  306.                 ::ShowWindow( mOSPort );
  307.                 #endif
  308.                         
  309.                 #if WINAMP
  310.                 ::ShowWindow( gWCModule.hwndParent, SW_SHOWNORMAL );
  311.                 #endif
  312.             } 
  313.                         
  314.             __restorePort
  315.         } } 
  316.     else if ( ! inFullScreen && mAtFullScreen ) {
  317.  
  318.         
  319.         // Restore the window
  320.         mPort.Deactivate();
  321.  
  322.         #if MACAMP
  323.         if ( gPlugInfo.ma -> ExitFullScreen )
  324.             gPlugInfo.ma -> ExitFullScreen();
  325.         #endif
  326.         
  327.         __setupPort
  328.  
  329.         SetWinPort( mOSPort, &mWinRectHolder );
  330.         
  331.         __restorePort
  332.         
  333.         mLastMousePt.h -= 55;        
  334.         mAtFullScreen = false;
  335.         
  336.         #if WINAMP
  337.         ::ShowWindow( gWCModule.hwndParent, SW_SHOWNORMAL );
  338.         #endif
  339.  
  340.     }
  341.     #endif
  342.  
  343.     if ( inFullScreen ) {
  344.     
  345.         // Changing the port (and the resolution) may change the mouse cords
  346.         EgOSUtils::GetMouse( mLastMousePt );
  347.  
  348.         // Default: mouse movement will not exit fullscreen mode
  349.         mMouseWillAwaken = false;    
  350.     }
  351.     
  352.     #if EG_MAC
  353.     ::FlushEvents( 0xFFFF, 0 );
  354.     #endif
  355. }
  356.  
  357.  
  358.  
  359. void WhiteCap::GetWinRect( Rect& outRect ) {
  360.     
  361.     if ( mOSPort ) {
  362.     
  363.         #if EG_MAC
  364.         outRect = (**(((CGrafPtr) mOSPort)->portPixMap)).bounds;
  365.         outRect.left *= -1;
  366.         outRect.top  *= -1;
  367.         outRect.right = outRect.left + mOSPort -> portRect.right;
  368.         outRect.bottom = outRect.top + mOSPort -> portRect.bottom;
  369.         #elif EG_WIN
  370.         RECT wr;
  371.         ::GetWindowRect( mOSPort, &wr );
  372.  
  373.         outRect.left    = wr.left; 
  374.         outRect.top        = wr.top;
  375.         outRect.right    = wr.right; 
  376.         outRect.bottom    = wr.bottom;
  377.         #endif 
  378.         }
  379.     else 
  380.         SetRect( &outRect, 0, 0, 0, 0 );
  381. }
  382.  
  383.  
  384. void WhiteCap::RecordSample( long inCurTime, float inSpectrum[] ) {
  385.     
  386.     #if DATA_DUMP
  387.     mDumpData.Append( &inCurTime, 4 );
  388.     mDumpData.Append( inSpectrum, sizeof( float ) * NUM_SAMPLE_BINS );
  389.     
  390.     // Give the sample data to the window if we're not just dumping the sound data
  391.     #else
  392.     
  393.     // Loop thru all the panes in the window
  394.     for ( int i = 0; i < mNumWorlds; i++ ) {
  395.  
  396.         // Tell the world to take a new sound sample (if it wants)
  397.         mWorld[ i ] -> RecordSample( inCurTime, inSpectrum );
  398.     }
  399.     #endif
  400. }
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409. void WhiteCap::Draw() {
  410.     Rect    r;
  411.     Point    pt;
  412.     long    i, time = EgOSUtils::CurTimeMS();
  413.                 
  414.     
  415.     // Load a random waveshape every so often, and randomize things
  416.     if ( time > mNextShapeChange && mInSlideShowMode ) {
  417.     
  418.         // Load the next config in the (randomized) config list...
  419.         i = mConfigPlayList.FindIndexOf( mCurConfigNum );
  420.         
  421.         // Make a new play list if we've reached the end of the list...
  422.         if ( i >= mConfigPlayList.Count() ) {
  423.             mConfigPlayList.Randomize();
  424.             i = 0;
  425.         }
  426.         LoadConfig( mConfigPlayList.Fetch( i + 1 ) );
  427.     }
  428.     
  429.     
  430.     EgOSUtils::GetMouse( pt );
  431.     
  432.     // Check the mouse pos and record it as active if its been moved.      
  433.     if ( pt.h != mLastMousePt.h || pt.v != mLastMousePt.v ) {
  434.         mLastMousePt        = pt;
  435.         mLastActiveTime        = time;
  436.         if ( mAtFullScreen && mMouseWillAwaken )
  437.             SetFullScreen( false ); 
  438.     }
  439.     
  440.     // If we've been idle for too long, go into full screen mode and let mouse movement wake us 
  441.     if ( time - mLastActiveTime > mScrnSaverDelay && mScrnSaverDelay > 0 ) {
  442.         mLastActiveTime    = time;
  443.         SetFullScreen( true );
  444.         mMouseWillAwaken = true; 
  445.     }
  446.  
  447.     __setupPort    
  448.     
  449.     // Tell the PixPort we're about to start accessing it big time
  450.     mPort.BeginFrame();
  451.  
  452.     // Loop thru all the panes in the window and the the whitecap wave thingy
  453.     time = EgOSUtils::CurTimeMS();
  454.     for ( i = 0; i < mNumWorlds; i++ ) {
  455.  
  456.         // Tell the world to update itself to the offscreen draw port
  457.         mWorld[ i ] -> Render( time, mPort, r );
  458.         
  459.         // If we're drawing to a window, draw it right away
  460.         if ( mPort.IsFullscreen() )
  461.             mPort.UnionDirtyRect( &r );
  462.         else 
  463.             mPort.CopyBits( mOSPort, &r, &r );
  464.     }
  465.     
  466.     
  467.     // In the case we're using DrawSpocks, the cur port is the 'screen' port
  468.     GrafPtr port = mOSPort;
  469.     #if EG_MAC
  470.     if ( mPort.IsFullscreen() )
  471.         ::GetPort( &port );
  472.     #endif
  473.     
  474.     // For each pane/world, draw the title string...        
  475.     for ( i = 0; i < mNumWorlds; i++ ) {
  476.         
  477.         mWorld[ i ] -> DrawConfigName( port );
  478.  
  479.         // In mac land, we may need to tell the port to refresh the given rect on the screen
  480.         #if EG_MAC        
  481.         mPort.UnionDirtyRect( &mWorld[ i ] -> mTitleRect );
  482.         #endif
  483.     }
  484.  
  485.         
  486.     //__setupPort
  487.  
  488.     #if EG_MAC
  489.     
  490.     // If the option key is down, show the frame rate
  491.     unsigned char km[16];
  492.     ::GetKeys( (unsigned long*) km );
  493.     i = 58;    
  494.     if ( ((km[ i >> 3 ] >> (i & 7)) & 1) != 0 ) {
  495.     
  496.         // Calc frame rate, show the current computation for frames
  497.         if ( time - mFrameCountStart >= 1500 ) {
  498.             mFramesPer10Secs = 10000 * mFrameCount / ( time - mFrameCountStart );
  499.             mFrameRate.Assign( mFramesPer10Secs );
  500.             mFrameRate.Insert( mFrameRate.length() - 1, ".", 1 );
  501.             mFrameCountStart = time;
  502.             mFrameCount = 0;
  503.         }
  504.         mFrameCount++;
  505.     
  506.         Rect r = { 0, 0, 20, 40 };
  507.         ::EraseRect( &r );
  508.         ::MoveTo( 5, 15 );
  509.         ::DrawString( mFrameRate.getPasStr() );
  510.         if ( mPort.IsFullscreen() )
  511.             mPort.UnionDirtyRect( &r );
  512.     }
  513.     #endif
  514.  
  515.  
  516.     mPort.EndFrame();
  517.  
  518.     __restorePort
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530. #define ___max( a, b ) (( (a) > (b) ) ? (a) : (b))
  531. #define ___maxSide( r ) (___max( r.right - r.left, r.bottom - r.top ))
  532.  
  533.  
  534. void WhiteCap::SetWinPort( GrafPtr inWin, const Rect* inRect ) {
  535.     Rect r;
  536.     
  537.     // mDoingSetPortWin == true is a signal that another thread is in SetWinPort()
  538.     if ( mDoingSetPortWin )
  539.         return;
  540.     mDoingSetPortWin = true;
  541.         
  542.     if ( inRect )
  543.         r = *inRect;
  544.     
  545.     // If an invalid win rect, fix it, you monkey!
  546.     if ( r.right - r.left < 20  || r.bottom - r.top < 20 || ! inRect ) {
  547.     
  548.         r.top                = mPrefs.GetPref( 'wTop' );
  549.         r.left                = mPrefs.GetPref( 'wLft' );
  550.         r.right                = mPrefs.GetPref( 'wRgt' );
  551.         r.bottom            = mPrefs.GetPref( 'wBot' );
  552.         
  553.         #if EG_MAC
  554.         // Invalidate the window if it's offscreen...
  555.         RgnHandle deskRgn = ::GetGrayRgn();
  556.         ::SectRect( &(*deskRgn) -> rgnBBox, &r, &r );
  557.         #endif
  558.     }
  559.  
  560.     // If no prefs avail (or an older version, use factory rect) or a bad win, hard code a size
  561.     if ( mPrefs.GetPref( 'Vers' ) != 30 || r.right - r.left < 20  || r.bottom - r.top < 20 ) {
  562.         r.top = 50;
  563.         r.left = 15;
  564.         r.right = 480;
  565.         r.bottom = 380; 
  566.     }
  567.  
  568.     long x = r.right - r.left;
  569.     long y = r.bottom - r.top;
  570.     
  571.             
  572.     #if EG_MAC
  573.     ::MoveWindow( inWin, r.left, r.top, true );
  574.     ::SizeWindow( inWin, x, y, true ); 
  575.     ::ShowWindow( inWin );
  576.     #else
  577.     RECT cr;
  578.     
  579.     // Resize the window and find the rgn we have to work with
  580.     ::MoveWindow( inWin, r.left, r.top, x, y, false );
  581.     ::GetClientRect( inWin, &cr );
  582.     x = cr.right - cr.left;
  583.     y = cr.bottom - cr.top;
  584.     #endif
  585.     
  586.     // The playpen for WhiteCap will be the entire window client rgn (what we'll give SetPort)
  587.     Rect portRect;
  588.     ::SetRect( &portRect, 0, 0, x, y );
  589.     SetPort( inWin, portRect, false );
  590.  
  591.     // Signal that this thread is done with SetPortWin()
  592.     mDoingSetPortWin = false;
  593. }
  594.  
  595.  
  596.  
  597.  
  598.  
  599. void WhiteCap::SetPort( GrafPtr inPort, const Rect& inRect, bool inFullScreen ) {
  600.     long x = inRect.right - inRect.left;
  601.     long y = inRect.bottom - inRect.top;
  602.  
  603.     mOSPort = inPort;
  604.     mPort.Init( x, y );
  605.     mDispRect = inRect;
  606.     mAtFullScreen = inFullScreen;
  607.     
  608.     __setupPort
  609.     
  610.     
  611.     // If we're brand spankin new, show at least 1 config, you monkey
  612.     if ( mNumWorlds == 0 )
  613.         LoadConfig( mCurConfigNum );
  614.     
  615.     __restorePort
  616.         
  617.     for ( int i = 0; i < mNumWorlds; i++ )
  618.         mWorld[ i ] -> ExpireSamples();
  619.         
  620.     ResizeWorlds();
  621. }
  622.  
  623.  
  624.  
  625.     
  626. void WhiteCap::ResizeWorlds() {
  627.     Rect r;
  628.     long i, j, bestLen, cutLen, best;
  629.  
  630.     
  631.     // Resize the panes in this window...
  632.     mWorld[ 0 ] -> SetPaneRect( mDispRect );
  633.     for ( i = 1; i < mNumWorlds; i++ ) {
  634.         
  635.         // Find the best world to cut in half
  636.         for ( bestLen = -1, j = 0; j < i; j++ ) {
  637.             cutLen = ___maxSide( (*mWorld[ j ] -> PaneRect()) );
  638.             if ( cutLen >= bestLen ) {
  639.                 bestLen = cutLen;
  640.                 best = j;
  641.             }
  642.         }
  643.         
  644.         // Change the pane rect of both the unplaced world and the world that's about to get cut in half
  645.         r = *(mWorld[ best ] -> PaneRect());
  646.         if ( r.right - r.left == bestLen ) {
  647.             r.right -= bestLen / 2;
  648.             mWorld[ best ] -> SetPaneRect( r );
  649.             OffsetRect( &r,  bestLen / 2,  0 );
  650.             mWorld[ i ] -> SetPaneRect( r ); }
  651.         else {
  652.             r.bottom -= bestLen / 2;
  653.             mWorld[ best ] -> SetPaneRect( r );
  654.             OffsetRect( &r,  0,  bestLen / 2 );
  655.             mWorld[ i ] -> SetPaneRect( r ); 
  656.         }                
  657.     }
  658. }
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668. void WhiteCap::RefreshRect( const Rect& inUpdate ) {
  669.  
  670.     for ( int i = 0; i < mNumWorlds; i++ ) {
  671.         mWorld[ i ] -> RefreshRect( inUpdate );        
  672.     }
  673. }
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681. void WhiteCap::LoadConfig( int inConfigNum ) {
  682.     const CEgFileSpec* configSpec;
  683.     int i, exists;
  684.     long oldNumWorlds = mNumWorlds;
  685.     long transitionTime = EgOSUtils::Rnd( mTransitionLo * 1000, mTransitionHi * 1000 );
  686.  
  687.         
  688.     mNumWorlds = 0;
  689.     mCurConfigNum = -1;
  690.     
  691.     // Fetch the spec for our config file or folder
  692.     configSpec = mConfigs.FetchSpec( inConfigNum );
  693.     
  694.     if ( configSpec ) {
  695.  
  696.          // If we have a folder or file...
  697.          exists = configSpec -> Exists();
  698.         if ( exists == 2 ) {
  699.             CEgFileSpec spec;
  700.             
  701.             bool startOver = true;
  702.             while ( EgOSUtils::GetNextFile( *configSpec, spec, startOver, false ) ) {
  703.                 if ( mNumWorlds >= oldNumWorlds )
  704.                     mWorld[ mNumWorlds ] = new WhiteCapWorld;
  705.                 mWorld[ mNumWorlds ] -> Init( &spec, transitionTime );
  706.                 mNumWorlds++;
  707.                 startOver = false;
  708.             }
  709.         }
  710.         
  711.         // Know what to put a check mark next to in the popup menu
  712.         mCurConfigNum = inConfigNum;
  713.     }
  714.     
  715.     // If it's only one config file or there's no spec specifed
  716.     if ( mNumWorlds == 0 ) {
  717.         mNumWorlds = 1;
  718.         if ( mNumWorlds > oldNumWorlds )
  719.             mWorld[ 0 ] = new WhiteCapWorld;
  720.         mWorld[ 0 ] -> Init( configSpec, transitionTime );
  721.     }
  722.     
  723.     for ( i = mNumWorlds; i < oldNumWorlds; i++ )
  724.         delete mWorld[ i ];
  725.     
  726.     
  727.     // If the cursor was spun, init it back to the ptr
  728.     EgOSUtils::ResetCursor();
  729.  
  730.     // Make sure all WhiteCap's configs live happily inside the allowed draw area
  731.     ResizeWorlds();
  732.  
  733.     // Set the time for when we load a random config automatically
  734.     mNextShapeChange = EgOSUtils::CurTimeMS() + mSlideShowInterval + transitionTime;
  735.  
  736.     // Very annoying:  in Win32, the call to GetWindowRect() is returning garbage in ~WhiteCap(), so just 
  737.     // forget about saving the window position for now in windows :_(
  738.     #if EG_WIN
  739.     if ( ! mAtFullScreen )
  740.         GetWinRect( mWinRectHolder );
  741.     #endif
  742.  
  743.     if ( mAtFullScreen )
  744.         EgOSUtils::HideCursor();
  745. }
  746.  
  747.  
  748.  
  749.  
  750. void WhiteCap::BuildConfigList( CEgFileSpec& inPluginsFolder ) {
  751.     CEgFileSpec spec;
  752.     bool startOver = true;
  753.     int i;
  754.         
  755.     while ( EgOSUtils::GetNextFile( inPluginsFolder, spec, startOver, false ) ) {
  756.         mConfigs.AddCopy( spec );
  757.         startOver = false;
  758.     }
  759.     
  760.     startOver = true;
  761.     while ( EgOSUtils::GetNextFile( inPluginsFolder, spec, startOver, true ) ) {
  762.         mConfigs.AddCopy( spec );
  763.         startOver = false;
  764.     }
  765.     
  766.     // Always have a item called (Default) in the config list
  767.     UtilStr        def( "(Default)" );
  768.     spec.Assign( inPluginsFolder );
  769.     if ( ! mConfigs.Lookup( def ) ) {
  770.         spec.Rename( def );
  771.         mConfigs.AddCopy( spec );
  772.     }
  773.     mCurConfigNum = mConfigs.Lookup( def );
  774.  
  775.     // Build a random config 'play' list
  776.     mConfigPlayList.RemoveAll();
  777.     for ( i = mConfigs.Count(); i > 0; i-- ) 
  778.         mConfigPlayList.Add( i );
  779.     mConfigPlayList.Randomize();    
  780. }
  781.  
  782.  
  783.  
  784.